/*
 * @Author: unhum 
 * @Date: 2018-06-30 17:00:45 
 * @Last Modified by: unhum
 * @Last Modified time: 2018-06-30 17:47:58
 */

;(function(global){
    "use strict";

    var _device = 0,            
        tools = [
            { icon: 'fa-refresh', name: 'refresh', fn: 'refresh()' },
            { icon: 'fa-th-large', name: 'color', fn: 'setColor(this)' },
            { icon: 'fa-eraser', name: 'eraser', fn: 'toggleEraser(this)' },
            { icon: 'fa-paint-brush', name: 'paint-brush', fn: 'setConfig("lineWidth",10,this)' },
            { icon: 'fa-arrows-alt', warning: '画板尺寸变化后，内容将丢失', name: 'arrows-alt', fn: 'resize(this,"all")' },
            { icon: 'fa-download', name: 'download', fn: 'download()' }            
        ],
        color_list = [
            { color: 'white', name: '白色' },
            { color: 'black', name: '黑色' },
            { color: 'yellow', name: '黄色' },
            { color: '#ffd700', name: '金黄色' },
            { color: '#292421', name: '象牙黑' },
            { color: '#ffffcd', name: '白杏仁' },
            { color: '#d2691e', name: '巧克力色' },
            { color: '#9933fa', name: '淡紫色' },
            { color: 'blue', name: '蓝色' },
            { color: 'red', name: '红色' },
            { color: '#b03060', name: '栗色' }
        ];

    // 获取滚动条信息
    function getScrollInfo(params) {
        var scroll = 0;
        if (document.documentElement && document.documentElement[params]) {
            scroll = document.documentElement[params];
        } else if (document.body) {
            scroll = document.body[params];
        }
        return scroll;
    };

    //获取当前设备
    function getDevice() {
        var sUserAgent = navigator.userAgent.toLowerCase();
        var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
        var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
        var bIsMidp = sUserAgent.match(/midp/i) == "midp";
        var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
        var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
        var bIsAndroid = sUserAgent.match(/android/i) == "android";
        var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
        var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
        if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
            _device = 1;
        } else {
            _device = 0;
        }
    };

    //取消事件冒泡
    function stopBubble(e) {
        //一般用在鼠标或键盘事件上
        if (e && e.stopPropagation) {
            //W3C取消冒泡事件
            e.stopPropagation();
        } else {
            //IE取消冒泡事件
            window.event.cancelBubble = true;
        }
    };

    var signature = function(params) {
        if (!params || !params.dom) return alert('必填参数不能为空');
        this.dom = params.dom;
        this.width = params.width || document.querySelector(this.dom).offsetWidth;
        this.height = params.height || document.querySelector(this.dom).offsetHeight;
        this.theme = params.theme || 'WB'; //WB：经典黑线白底 BW：白线黑底
        this.lineWidth = params.lineWidth || 1;
        this.follow = params.follow ? true : false;
        this.console = params.console == false ? false : true;
        this.consoleHeight = 0;
        this.eraser = false;
        this.tname = params.tname || 'signature';
        this.tmp = {};
        
        var that = this;

        function create(ele) {
            if (that.console) {
                var div = document.createElement('div');
                div.classList.add('signature-console');
                // 初始化工具栏
                for (var i = 0; i < tools.length; i++) {
                    var _i = document.createElement('i');
                    _i.setAttribute('onclick', that.tname + '.' + tools[i].fn);
                    _i.classList.add(tools[i].icon);
                    _i.classList.add('fa');
                    _i.innerHTML = '<span>' + tools[i].name + '</span>';
                    if (tools[i].class) {
                        _i.classList.add(tools[i].class);
                    }
                    if (tools[i].warning) {
                        var warning = document.createElement('div');
                        warning.innerHTML = tools[i].warning;
                        warning.classList.add('signature-warning');
                        _i.appendChild(warning);
                    }
                    div.appendChild(_i);
                }
                document.querySelector(ele.dom).appendChild(div);
                //记录控制台高度
                that.consoleHeight = document.querySelector(that.dom).querySelector('.signature-console').clientHeight;
            }
            var c = document.createElement('canvas');
            c.innerHTML = '请升级您的浏览器或者更换您的浏览器。';
            c.style.background = ele.bg;
            c.width = ele.width;
            c.height = that.console ? ele.height - that.consoleHeight : ele.height;
            document.querySelector(ele.dom).appendChild(c);
            ele.canvas = c;
    
            // 相应容器变化
            window.addEventListener('resize', function () {
                if (that.width != document.querySelector(that.dom).offsetWidth) {
                    that.canvas.width = document.querySelector(that.dom).offsetWidth;
                    that.width = document.querySelector(that.dom).offsetWidth;
                }
            })
        };

        function init() {
            switch (that.theme) {
                case 'WB':
                    that.color = 'black';
                    that.bg = 'white';
                    break;
                case 'BW':
                    that.color = 'white';
                    that.bg = 'black';
                    break;
                default:
                    that.color = 'black';
                    that.bg = 'white';
                    break;
            }
            that.color = params.color ? params.color : that.color;
            that.bg = params.bg ? params.bg : that.bg;
            
            // 初始化canvas
            create(that);

            // 记录原有属性
            for (var x in that) {
                that.tmp[x] = that[x];
            };

            // 判断客户端设备
            getDevice();

            that.canvas.addEventListener(_device == 0 ? 'mousedown' : 'touchstart', function (event) {
                //取消默认事件
                event.preventDefault();
                that.fnDown(event);
            })
        };

        // 初始化
        init();
    };

    signature.prototype = {
        fnMove: function (event) {
            var e = event || window.event;
            if (_device == 1) e = e.touches[0];
            var position = {
                left: document.querySelector(this.dom).offsetLeft,
                top: this.canvas.offsetTop
            };
            var x = (_device == 0 ? e.clientX : e.pageX) - position.left + getScrollInfo('scrollLeft');
            var y = (_device == 0 ? e.clientY : e.pageY) - position.top + getScrollInfo('scrollTop');
            this.pen.lineTo(x, y);
            this.pen.stroke();
        },
        createTools: function (params, fn) {
            if (!params) {
                alert('请填写相关参数');
                return
            };
    
            if (this.console) {
                var _SIGNATURE = this;
                // 用户自定义添加工具
                var CONSOLE = document.querySelector(this.dom).querySelector('.signature-console');
                var i = document.createElement('i');
                i.onclick = fn ? function () { fn(_SIGNATURE) } : function () { alert('请填写方法') };
                i.innerHTML = '<span>' + (params.name ? params.name : 'Untitled tool') + '</span>';
                i.setAttribute('class', params.icon ? params.icon + ' fa' : 'fa-gear fa');
                if (params.class) {
                    i.classList.add(tools[i].class);
                }
                if (params.warning) {
                    var warning = document.createElement('div');
                    warning.innerHTML = params.warning;
                    warning.classList.add('signature-warning');
                    i.appendChild(warning);
                }
                CONSOLE.appendChild(i);
            }
        },
        download: function () {
            var type = 'png';
            var imgData = this.canvas.toDataURL();
            // 修改图片类型,强制下载
            var _fixType = function (type) {
                type = type.toLowerCase().replace(/jpg/i, 'jpeg');
                var r = type.match(/png|jpeg|bmp|gif/)[0];
                return 'image/' + r;
            };
            imgData = imgData.replace(_fixType(type), 'image/octet-stream');
            // 保存图片到本地
            var saveFile = function (data, filename) {
                var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
                save_link.href = data;
                save_link.download = filename;
    
                var event = document.createEvent('MouseEvents');
                event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                save_link.dispatchEvent(event);
            };
            // 设置图片名称
            var filename = 'signature_' + (new Date()).getTime() + '.' + type;
            // download
            saveFile(imgData, filename);
        },
        fnDown: function (event) {
            var e = event || window.event;
            var _dom = document.querySelector(this.dom);
            var position = {
                left: document.querySelector(this.dom).offsetLeft,
                top: this.canvas.offsetTop
                // - (this.console ? : 0)
            };
            if (_device == 1) e = e.touches[0];
            var x = (_device == 0 ? e.clientX : e.pageX) - position.left + getScrollInfo('scrollLeft');
            var y = (_device == 0 ? e.clientY : e.pageY) - position.top + getScrollInfo('scrollTop');
            //初始化"画笔"
            this.pen = this.canvas.getContext('2d');
            //绘制开始
            this.pen.beginPath();
            if (_dom.querySelector('.signature-console')) {
                this.pen.strokeStyle = _dom.querySelector('.fa-eraser').classList.contains('active') ? this.bg : this.color;
                this.pen.lineWidth = _dom.querySelector('.fa-eraser').classList.contains('active') ? this.lineWidth + 4 : this.lineWidth - 1;
            } else {
                this.pen.strokeStyle = this.color;
                this.pen.lineWidth = this.lineWidth - 1;
            }
            this.pen.shadowBlur = 1;
            this.pen.shadowColor = this.color;
    
            if (_dom.querySelector('.signature-console')) {
                _dom.querySelector('.fa-eraser').classList.contains('active') ? this.pen.shadowColor = this.bg : this.pen.shadowColor = this.color;
            }
    
            this.pen.lineTo(x, y);
    
            var _this = this;
    
            //创建用户滑动轨迹
            _device == 0 ? document.onmousemove = function (event) {
                _this.fnMove(event);
            } : document.addEventListener('touchmove', function (event) {
                //取消默认事件
                event.preventDefault();
                _this.fnMove(event);
            });
    
            //终止签名
            window.addEventListener(_device == 0 ? 'mouseup' : 'touchend', function (event) {
                _this.fnUp(event);
            });
        },
        fnUp: function () {
            this.pen.closePath();
            document.onmousemove = '';
        },
        toggleEraser(ele) {
            this.active(ele);
        },
        refresh: function () {
            if (this.pen) {
                this.pen.clearRect(0, 0, this.canvas.width, this.canvas.height);
            }
        },
        active: function (ele, status, fn) {
            if (status == true) {
                fn();
            } else {
                ele.classList.contains('active') ? ele.classList.remove('active') : ele.classList.add('active');
            }
        },
        selectColor: function (ele, color, event) {
            var e = event || window.event;
            var _this = this;
            // 取消事件冒泡
            stopBubble(e);
            ele.classList.contains('select') ? function () {
                ele.classList.remove('select');
                _this.color = _this.tmp.color;
            }() : function () {
                var _dom = document.querySelector(_this.dom);
                for (var i = 0; i < _dom.querySelectorAll('.signature-set-color > div').length; i++) {
                    _dom.querySelectorAll('.signature-set-color > div')[i].classList.remove('select');
                }
                _dom.querySelector('.signature-set-color').style.display = 'none';
                _this.color = color;
                ele.classList.add('select');
            }()
        },
        setColor: function (ele) {
            var _this = this;
            var signature_set_color = ele.querySelector('.signature-set-color');
            // 添加样式
            this.active(ele, true, function () {
                if (ele.querySelector('.signature-set-color .select')) {
                    signature_set_color.style.display = 'block';
                } else {
                    ele.classList.contains('active') ? ele.classList.remove('active') : ele.classList.add('active');
                }
            });
            if (ele.classList.contains('active')) {
                if (signature_set_color) {
                    signature_set_color.style.display = 'block';
                } else {
                    // 创建颜色框
                    var div = document.createElement('div');
                    div.classList.add('signature-set-color');
                    div.style.width = Math.ceil((this.width / 2 - 10) / 34) * 34 + 'px';
                    for (var i = 0; i < color_list.length; i++) {
                        var color = document.createElement('div');
                        color.classList.add('color');
                        color.title = color_list[i].name;
                        color.setAttribute('onclick', this.tname + '.selectColor(this,"' + color_list[i].color + '",event)');
                        color.style.background = color_list[i].color;
                        div.appendChild(color);
                    }
                    ele.appendChild(div);
                }
            } else {
                signature_set_color.style.display = 'none';
                this.color = this.tmp.color;
            }
        },
        setConfig: function (params, num, ele) {
            var _this = this;
            if (ele.classList.contains('active')) {
                ele.classList.remove('active');
                _this[params] = _this.tmp[params];
            } else {
                ele.classList.add('active');
                _this[params] = num;
            }
        },
        config: function (params) {
            params.dom ? function () {
                alert('禁止修改dom');
                return
            }() : function () {
                for (var p in params) {
                    _this[p] = params[p];
                }
            }()
        },
        resize: function (ele, w, j) {
            var _this = this;
            _this.active(ele, true, function () {
                var _dom = document.querySelector(_this.dom);
                if (ele.classList.contains('active')) {
                    ele.classList.remove('active');
                    _dom.classList.remove('signature-full');
                    _this.canvas.width = _this.tmp.width;
                    _this.canvas.height = _this.console ? _this.tmp.height - _this.consoleHeight : _this.tmp.height;
                } else {
                    ele.classList.add('active');
                    if (w == 'all') {
                        _dom.classList.add('signature-full');
                        _this.canvas.width = document.documentElement.clientWidth;
                        _this.canvas.height = document.documentElement.clientHeight;
                    } else {
                        _dom.style.width = w;
                        _dom.style.height = h;
                        _this.canvas.width = document.documentElement.clientWidth;
                        _this.canvas.height = document.documentElement.clientHeight;
                    }
                }
            })
        }   
    };

    if (typeof exports === 'object' && typeof module !== 'undefined' && module.exports) module.exports = signature;
    if (typeof define === 'function' && define.amd) define(function () { return signature; });
    global.csignature = signature;

})(this)